package com.lemon.components.ant.swagger.net;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.lemon.components.ant.swagger.net.dto.GetBaseDocReq;
import com.lemon.components.ant.swagger.net.dto.GetBaseDocRsp;
import com.lemon.components.ant.swagger.net.dto.ModelItem;
import com.lemon.components.ant.swagger.net.dto.ModelItem.ItemData;
import com.system.core.utils.HttpUtils;

import lombok.experimental.UtilityClass;

@UtilityClass
public class DocBase {

	public GetBaseDocRsp getBaseDocs(GetBaseDocReq req) throws Exception {
		JSONObject baseJson = JSONObject.parseObject(HttpUtils.get(req.getDocBaseUrl()));
		JSONObject apiObject = (JSONObject)JSONPath.eval(baseJson, "$.paths");
		JSONObject temp = apiObject.getJSONObject(req.getApiUrl());
		JSONArray testobj = (JSONArray)JSONPath.eval(temp, "$."+req.getMethod()+".parameters");
		String responseSchemaJsonPath = (String)JSONPath.eval(temp, "$."+req.getMethod()+".responses.200.schema.$ref");
		JSONObject responseJSONS = (JSONObject)JSONPath.eval(baseJson, "$.definitions");
		String[] absSchemaName = responseSchemaJsonPath.split("/");
		JSONObject responseJSON = (JSONObject)responseJSONS.getJSONObject(absSchemaName[absSchemaName.length-1]);
		String schemaPath = findSchema(testobj);
		JSONObject requestJSON;
		if(StringUtils.isNotBlank(schemaPath)) {
			requestJSON = (JSONObject)JSONPath.eval(baseJson, schemaPath.replace("#", "$").replace("/", "."));
		} else {
			requestJSON = null;
			
		}
		
		JSONObject obj = (JSONObject)JSONPath.eval(responseJSON, "$.properties");
		GetBaseDocRsp getBaseDocRsp = null;
		for(String key:obj.keySet()) {
			JSONObject tmp = obj.getJSONObject(key);
			if(req.isTableResult() && "array".equalsIgnoreCase(tmp.getString("type"))) {
				String refstr = (String)JSONPath.eval(tmp, "$.items.$ref");
				responseJSON = (JSONObject)JSONPath.eval(baseJson, refstr.replace("#", "$").replace("/", "."));
			} else if (key.equalsIgnoreCase("data")) {
				String refstr = (String)JSONPath.eval(tmp, "$.$ref");
				responseJSON = (JSONObject)JSONPath.eval(baseJson, refstr.replace("#", "$").replace("/", "."));
			}
		}
		if(StringUtils.isNotBlank(schemaPath)) {
			getBaseDocRsp = new GetBaseDocRsp(requestJSON,responseJSON,getSchemaProperties(requestJSON),getSchemaProperties(responseJSON));
		}else {
			getBaseDocRsp = new GetBaseDocRsp(requestJSON,responseJSON,getProperties(testobj),getSchemaProperties(responseJSON));
		}
		
		return getBaseDocRsp;
	}
	
	public String findSchema(JSONArray parameters) {
		final StringBuilder tmp = new StringBuilder();
		parameters.forEach((item)->{
			JSONObject obj = (JSONObject)item;
			JSONObject ref = obj.getJSONObject("schema");
			if(ref != null) {
				tmp.append(ref.getString("$ref")) ;
			}
		});
		return tmp.toString();
	}
	
	public List<ModelItem> getSchemaProperties(JSONObject paramJSON) {
		if(paramJSON==null)
			return null;
		JSONObject obj = (JSONObject)JSONPath.eval(paramJSON, "$.properties");
		List<ModelItem> models = new ArrayList<>();
		for(String key:obj.keySet()) {
			JSONObject tmp = obj.getJSONObject(key);
			List<ItemData> itemDataList = getItemDataList(tmp.getString("description"));
			String type = tmp.getString("type");
			if(StringUtils.isBlank(type)) {
				type=tmp.getString("$ref");
			}
			ModelItem item = ModelItem.builder()
					.name(key)
					.type(type)
					.hasItemData(itemDataList.size()>0?true:false)
					.items(itemDataList)
					.format(tmp.getString("format"))
					.description(tmp.getString("description"))
					.build();
			models.add(item);
		}
		return models;
	}
	
	public List<ModelItem> getProperties(JSONArray paramJSON){
		List<ModelItem> models = new ArrayList<>();
		paramJSON.forEach(jsonobj->{
			JSONObject obj = (JSONObject)jsonobj;
			if(obj.getString("name")!=null && !obj.getString("name").equalsIgnoreCase("token")) {
				List<ItemData> itemDataList = getItemDataList(obj.getString("description"));
				ModelItem item = ModelItem.builder()
						.name(obj.getString("name"))
						.type(obj.getString("type"))
						.hasItemData(itemDataList.size()>0?true:false)
						.items(itemDataList)
						.format(obj.getString("format"))
						.description(obj.getString("description"))
						.build();
				models.add(item);
			}
		});
		return models;
	}

	public List<ModelItem.ItemData> getItemDataList(String description){
		List<ModelItem.ItemData> list = new ArrayList<>();
		if(StringUtils.isBlank(description))
			return list;
		Pattern pattern = Pattern.compile("\\d+-.*(?=\\W)",Pattern.CASE_INSENSITIVE);
		Matcher m = pattern.matcher(description);
		String matchstr=null;
		if (m.find()) {
			matchstr = m.group(0);
		} else {
			return list;
		}
		
		String[] splitChars1= {";","，","；",","};
		String[] splitChars2= {"-","->"};
		String[] s1;
		for(String splitChar1: splitChars1) {
			s1 = matchstr.split(splitChar1);
			if(s1.length>1) {
				for(String t1:s1) {
					ModelItem.ItemData itemData = new ModelItem.ItemData();
					for(String splitChar2: splitChars2) {
						String[] s2 = t1.split(splitChar2);
						if(s2.length>1) {
							itemData.setCode(s2[0]);
							itemData.setValue(s2[1]);
							list.add(itemData);
							break;
						}
					}
				}
				break;
			}
		}
		
		return list;
	}

	public static void main(String[] args) throws Exception {
//		GetBaseDocRsp result = DocBase.getBaseDocs(GetBaseDocReq.builder()
//				.docBaseUrl("https://xw.tst.cqtancheng.com/v3/api-docs?group=tanqiqi")
//				.apiUrl("/boss/zone/zone-add")
//				.method(HttpMethod.post).build());
//		System.out.println(result.getRequest());
		String temp = "审核状态：1-待审核，2-审核通过，3-审核拒绝";
		List<ItemData> list = DocBase.getItemDataList(temp);
		for(ItemData itemdata:list) {
			System.out.println(itemdata.toString());
		}
	}
}
